﻿Option Strict On

Imports System.Timers
Imports VB = Microsoft.VisualBasic

Public Class Form1

    ' Use this Random object to choose random icons for the squares
    Private random As New Random

    Private firstClicked As Label = Nothing
    Private secondClicked As Label = Nothing

    Private FoundMatches As Integer
    Private TotalMatches As Integer
    Private TickCount As Integer
    Private MaxTickCount As Integer = 30
    Private MatchPause As Integer = 500
    Private SoundsEnabled As Boolean
    Private GameReady As Boolean

    Private FormSize As System.Drawing.Size

    Private StartPause As DateTime
    Private ElapsedPause As TimeSpan
    Private StartTime As DateTime
    Private ElapsedTime As TimeSpan

    Private PlayerId As Long
    Private PlayerName As String
    Private PlayerItem As String
    Private PlayerData As String
    Private PlayerArray() As Array
    Private PlayerList As New Specialized.StringCollection
    Private ListofIconLabels As New List(Of System.Windows.Forms.Label)

    Public Players As New Players
    Public Gameset As New Gameset

    Public Sub New()
        GameReady = False

        ' get user settings
        'My.Settings.Reset()   'to reset back to defaults, for debugging
        FormSize = My.Settings.FormSize
        MaxTickCount = My.Settings.MaxTickCount
        MatchPause = My.Settings.MatchPause
        SoundsEnabled = My.Settings.SoundsEnabled

        Call Players.LoadSettings(My.Settings.PlayerData, My.Settings.PlayerId)

        'load gameset from xml
        'GameSetFile = "badxml.xml"
        GameSetFile = My.Settings.GameSetFile
        XDocGameSet = Main.MyGameset.LoadGameSet(AppDir & GameSetFile)

        'load gamecard
        GameCard = My.Settings.GameCard
        GameCardType = My.Settings.GameCardType
        Main.MyGameset.GameCard = GameCard


        'colors
        IconBackColor = My.Settings.IconBackColor
        IconForeColor = My.Settings.IconForeColor
        If IconBackColor.IsEmpty Then IconBackColor = Color.White
        If IconForeColor.IsEmpty Then IconForeColor = Color.Black

        'Dim fntname As String
        Try
            GameCardFont = CType(My.Settings.Item("Font" & GameCard), System.Drawing.Font)
        Catch ex As Exception
            Dim GameCardFont As New System.Drawing.Font("Webdings", 72, FontStyle.Bold)
            AddProperty("Font" & GameCard, "", GetType(System.Drawing.Font))
            My.MySettings.Default.Reload()
            My.MySettings.Default.Item("Font" & GameCard) = CType(GameCardFont, System.Drawing.Font)
        End Try
        GameCardFont = CType(My.Settings.Item("Font" & GameCard), System.Drawing.Font)


        ' This call is required by Windows Form Designer
        InitializeComponent()

        ' collect labels with Tag=icon to be assigned an icon
        Dim iconLabel As Label
        For Each control In TableLayoutPanel1.Controls
            iconLabel = TryCast(control, Label)
            If iconLabel IsNot Nothing AndAlso iconLabel.Tag.ToString.StartsWith("icon") Then
                ListofIconLabels.Add(iconLabel)
            End If
        Next
        'Stop

        ' populate form based on saved settings
        If Not My.Settings.FormSize.IsEmpty Then Me.Size = FormSize

        'EnableSoundsToolStripMenuItem.Checked = SoundsEnabled

        'load players data
        Call LoadPlayersData()

        'Call Main.MyGameset.AssignColorsToSquares(ListofIconLabels)

        'Call StopGame()

        Call Main.MyGameset.SetIconSquares(ListofIconLabels, ShowIcons:=False, EnableIcons:=False)
        GameReady = True
    End Sub


    Public Sub StartGame()
        ToolsToolStripMenuItem.Enabled = False
        AddPlayerButton.Enabled = False
        RemovePlayerButton.Enabled = False
        RenamePlayerButton.Enabled = False
        AddPlayerButton.Enabled = False
        ClearStatsButton.Enabled = False

        TickCount = 0
        IconSquareCount = 16
        FoundMatches = 0
        TotalMatches = CInt(IconSquareCount / 2)

        ' Reset timer 
        StartTime = Nothing
        StartPause = Nothing
        LabelTimer.Text = "0.00"
        Timer2.Enabled = True

        ' Reset firstClicked and secondClicked 
        firstClicked = Nothing
        secondClicked = Nothing

        'load gamecard
        Main.MyGameset.IconCount = TotalMatches
        Call Main.MyGameset.LoadGameCard(GameCard)
        Call Main.MyGameset.AssignIconsToSquares(ListofIconLabels, True)
        Call Main.MyGameset.SetIconSquares(ListofIconLabels, ShowIcons:=True, EnableIcons:=True)
        'Call Main.MyGameset.LoadGameCard("UpperCase")
        'Call Main.MyGameset.LoadGameCard("Sample Pictures")
        'Call Main.MyGameset.LoadGameCard("Sample Folder")

        Timer2.Start()
    End Sub


    Public Sub StopGame()
        'Stop
        Timer2.Enabled = False
        Timer2.Stop()

        ToolsToolStripMenuItem.Enabled = True
        RemovePlayerButton.Enabled = True
        RenamePlayerButton.Enabled = True
        AddPlayerButton.Enabled = True
        ClearStatsButton.Enabled = True
        Call Main.MyGameset.ShowIcons(ListofIconLabels)
        'ShowIcons()
    End Sub


    ''' <summary>
    ''' Assign each icon from the list of icons to a random square
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub AssignIconsToSquares()
        Dim ListofInt As New List(Of Integer)
        ListofInt = RandomIndex(TotalMatches)

        'Stop
        Dim StringDelimiter As String = "|"

        ' letter icons in the Webdings font
        Dim GameCardString As String = "!|N|,|k|b|v|w|z"

        ' repeat the string twice
        GameCardString = GameCardString & StringDelimiter & GameCardString

        ' make it a list
        Dim GameCardArray() As String = GameCardString.Split(CChar(StringDelimiter))
        Dim icons As List(Of String) = GameCardArray.ToList()

        'Dim icons =
        '  New List(Of String) From {"!", "!", "N", "N", ",", ",", "k", "k",
        '                            "b", "b", "v", "v", "w", "w", "z", "z"}

        ' labels with Tag=icon are assigned an icon
        For Each control In ListofIconLabels
            'For Each control In TableLayoutPanel1.Controls
            Dim iconLabel = TryCast(control, Label)

            'If iconLabel IsNot Nothing AndAlso iconLabel.Tag Is "icon" Then
            'hide icons
            iconLabel.ForeColor = IconBackColor
            iconLabel.Enabled = True

            'Dim randomNumber = random.Next(icons.Count)
            'iconLabel.Text = icons(randomNumber)
            'icons.RemoveAt(randomNumber)
            'End If
        Next

    End Sub


    ''' <summary>
    ''' Assign color background to icon squares
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub AssignColorsToSquares()
        'Dim img1 As New Bitmap(AppDir & "my photo.jpg")
        'Dim img2 As New Bitmap(img, Label10.Width, Label10.Height)

        Dim brightness As Single
        brightness = IconBackColor.GetBrightness
        If brightness < 0.5 Then
            IconForeColor = Color.White
        Else
            IconForeColor = Color.Black
        End If

        ' TableLayoutPanel labels with Tag=icon are assigned an icon
        For Each control In TableLayoutPanel1.Controls
            Dim iconLabel = TryCast(control, Label)

            If iconLabel IsNot Nothing AndAlso iconLabel.Tag Is "icon" Then
                iconLabel.ForeColor = IconForeColor
                iconLabel.BackColor = IconBackColor

                'img1 = System.Drawing.Image.FromFile(AppDir & "my photo.jpg")
                'img1.Size = iconLabel.Size
                'iconLabel.BackgroundImageLayout = ImageLayout.Stretch
                'iconLabel.BackgroundImage = img
                'iconLabel.BackgroundImage = Nothing
                'iconLabel.Image = img2
                'iconLabel.Image = Nothing
            End If
        Next

    End Sub


    ''' <summary>
    ''' Show icons and disable icon squares
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub ShowIcons()

        ' TableLayoutPanel labels with Tag=icon are assigned an icon
        For Each control In TableLayoutPanel1.Controls
            Dim iconLabel = TryCast(control, Label)

            If iconLabel IsNot Nothing AndAlso iconLabel.Tag Is "icon" Then
                iconLabel.ForeColor = IconForeColor
                iconLabel.Enabled = False
            End If
        Next

    End Sub


    ''' <summary>
    ''' Every icon square Click event is handled by this event handler
    ''' </summary>
    ''' <param name="sender">The label that was clicked</param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub label_Click(ByVal sender As System.Object,
                            ByVal e As System.EventArgs) Handles IconLabelR2C1.Click,
        IconLabelR1C4.Click, IconLabelR1C3.Click, IconLabelR1C2.Click, IconLabelR1C1.Click,
        IconLabelR2C4.Click, IconLabelR2C3.Click, IconLabelR2C2.Click, IconLabelR2C1.Click,
        IconLabelR3C4.Click, IconLabelR3C3.Click, IconLabelR3C2.Click, IconLabelR3C1.Click,
        IconLabelR4C4.Click, IconLabelR4C3.Click, IconLabelR4C2.Click, IconLabelR4C1.Click

        'timer that generates pause between two failed clicks and reset
        If Timer1.Enabled Then Exit Sub

        Dim clickedLabel = TryCast(sender, Label)
        If clickedLabel IsNot Nothing Then

            If StartPause = Nothing Then StartPause = Now()

            'icon already matched
            If clickedLabel.ForeColor = IconForeColor Then Exit Sub

            ' If firstClicked is Nothing, this is the first icon 
            ' in the pair that the player clicked, 
            ' so set firstClicked to the label that the player
            ' clicked, make it visible, and exit
            If firstClicked Is Nothing Then
                firstClicked = clickedLabel
                firstClicked.ForeColor = IconForeColor
                Debug.Print(firstClicked.Text)
                Exit Sub
            End If

            ' player clicked on icon already visible, ignore
            If firstClicked Is clickedLabel Then
                Exit Sub
            End If

            ' If the player gets this far, the timer isn't 
            ' running and firstClicked isn't Nothing, 
            ' so this must be the second icon the player clicked
            ' make it visible, and proceed to check for match
            secondClicked = clickedLabel
            secondClicked.ForeColor = IconForeColor
            Debug.Print(secondClicked.Text)


            ' If the player clicked two matching icons, keep them 
            ' visible and reset firstClicked and secondClicked to nothing
            If (GameCardType = "Text" And (firstClicked.Text = secondClicked.Text)) Or _
                (GameCardType = "Image" And (firstClicked.Tag Is secondClicked.Tag)) Then
                Debug.Print("Match")
                firstClicked = Nothing
                secondClicked = Nothing
                FoundMatches += 1
                If FoundMatches = TotalMatches Then
                    ElapsedPause = Now().Subtract(StartPause)
                    StopGame()

                    GameMessage = "You matched all the icons in "
                    If ElapsedPause.TotalMinutes > 1 Then GameMessage = GameMessage & CInt(ElapsedPause.TotalMinutes) & " minutes, "
                    GameMessage = GameMessage & Format(CStr(ElapsedPause.TotalSeconds), "Fixed") & " seconds!"
                    'GameMessage = GameMessage & (CInt(ElapsedPause.TotalSeconds) Mod 60) & " seconds!"

                    If SoundsEnabled Then GameSoundPlayer.Play()
                    Dim result = MessageBox.Show(GameMessage, "Congratulations", MessageBoxButtons.OK)

                    'update player game stats
                    Call Players.AddGame(CSng(ElapsedPause.TotalSeconds), MaxTickCount)
                    Call SetActivePlayer()
                End If
            Else
                ' interval timer
                Debug.Print("No Match")
                Timer1.Start()
            End If

        End If
    End Sub


    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        ' Stop the interval pause timer
        Timer1.Stop()
        Debug.Print("Hide")

        ' Hide both icons
        firstClicked.ForeColor = firstClicked.BackColor
        secondClicked.ForeColor = secondClicked.BackColor

        ' Reset firstClicked and secondClicked 
        firstClicked = Nothing
        secondClicked = Nothing

    End Sub

    Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        TickCount = TickCount + 1
        LabelTimer.Text = (TickCount \ 60) & ":" & (TickCount Mod 60)
        If TickCount >= MaxTickCount Then
            StopGame()
            MessageBox.Show("Sorry, you ran out of time", "Awwww shucks")
            Call Players.AddGame(MaxTickCount, MaxTickCount)
            Call SetActivePlayer()
        End If
        'Stop
    End Sub



    Private Sub SetGameTimeLimit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim myResult As String
        Dim ErrorMessage As String = ""
        Dim myMaxTime As Integer

        ErrorMessage = Chr(13) & "(Value must be positive integer.)"
        Do
            myResult = InputBox("Enter number of seconds" & ErrorMessage, "Max Time", CStr(MaxTickCount))

            ' If user has clicked Cancel, exit 
            If myResult = "" Then Exit Sub

            If IsNumeric(myResult) Then
                myMaxTime = CInt(Val(myResult))
            End If

            If myMaxTime < 1 Then
                myMaxTime = 0
            End If

        Loop Until myMaxTime > 0

        ' If nothing changed, exit 
        If myMaxTime = MaxTickCount Then Exit Sub

        MaxTickCount = myMaxTime
        My.Settings.MaxTickCount = MaxTickCount
        My.Settings.Save()

    End Sub

    Private Sub SetBackgroundColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Using colorDialog As New ColorDialog
            'If the user actually selected a color Then
            If colorDialog.ShowDialog() = DialogResult.OK Then
                'Set the background color
                IconBackColor = colorDialog.Color
                AssignColorsToSquares()
                My.Settings.IconBackColor = IconBackColor
                My.Settings.Save()
            End If
        End Using
    End Sub

    Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click
        StartGame()
    End Sub

    Private Sub StopButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopButton.Click
        Call Players.AddGame(MaxTickCount, MaxTickCount)
        Call SetActivePlayer()
        StopGame()
    End Sub

    Private Sub Form1_ResizeEnd(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.ResizeEnd
        My.Settings.FormSize = Me.Size
        My.Settings.Save()
    End Sub

    Private Sub SetGameCard_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SetGameCard.Click
        Dim frm2 As New Form2()
        frm2.xGameset = Gameset
        frm2.ShowDialog()
        'Stop
    End Sub

    Private Sub RemovePlayerButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RemovePlayerButton.Click

        Dim msg As String = Players.DeletePlayer()

        If msg = "" Then
            Call LoadPlayersData()
        Else
            MsgBox(msg)
            PlayerListBox.Text = Players.PlayerName
        End If

    End Sub

    Private Sub RenamePlayerButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RenamePlayerButton.Click
        Dim OldPlayer As String = PlayerListBox.Text
        Dim NewPlayer As String = InputBox("Edit name of player", "Rename Player", OldPlayer)

        If NewPlayer Is "" Then Exit Sub
        If NewPlayer Is OldPlayer Then Exit Sub

        Dim msg As String = Players.RenamePlayer(NewPlayer)

        If msg = "" Then
            Call LoadPlayersData()
        Else
            MsgBox(msg)
            PlayerListBox.Text = Players.PlayerName
        End If

    End Sub

    Private Sub AddPlayerButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddPlayerButton.Click

        Dim msg As String = Players.AddPlayer(PlayerListBox.Text)

        If msg = "" Then
            Call LoadPlayersData()
        Else
            MsgBox(msg)
            PlayerListBox.Text = Players.PlayerName
        End If

    End Sub

    Private Sub PlayerListBox_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PlayerListBox.SelectedIndexChanged
        'Stop
        Call Players.SetPlayer(PlayerListBox.Text)
        Call SetActivePlayer()
    End Sub

    Private Sub ClearStatsButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ClearStatsButton.Click
        Call Players.ClearStats()
        Call SetActivePlayer()
    End Sub

    Private Sub EnableSoundsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        EnableSoundsToolStripMenuItem.Checked = Not SoundsEnabled
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
        Call SavePlayersData()
        My.Settings.Save()
        'Stop
    End Sub



    ''' <summary>
    ''' load string from settings containing data for all players (id, name, stats, etc.)
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub LoadPlayersData()

        'clear listbox
        PlayerListBox.Items.Clear()

        'add player names
        For Each item As String In Players.GetPlayerNames
            PlayerListBox.Items.Add(item)
        Next

        'select active player
        PlayerListBox.Text = Players.PlayerName
        'Stop

    End Sub


    Private Sub SetActivePlayer()
        PlayerId = Players.PlayerId
        PlayerName = Players.PlayerName

        'show stats for active player
        LabelTotalGames.Text = CStr(Players.TotalGames)
        LabelFastestTime.Text = Format(CStr(Players.FastestTime), "Fixed")
        LabelAvgTime.Text = Format(CStr(Players.AverageTime), "Fixed")

        'Call SavePlayersData()
        'Stop

    End Sub


    Private Sub testing()
        'Call ImportGameSet(AppDir & GameSetFile)

        For Each value As Configuration.SettingsPropertyValue In My.Settings.PropertyValues
            If VB.Left(value.Name, 4) = "Font" Then
                MessageBox.Show(value.Name & " - " & value.PropertyValue.ToString)
            End If
        Next
        Stop

        'test example of configuration file locations
        'Dim exeConfig As System.Configuration.Configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None)
        'Debug.WriteLine(exeConfig.FilePath)

        'Dim localConfig As System.Configuration.Configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.PerUserRoamingAndLocal)
        'Debug.WriteLine(localConfig.FilePath)

        'Dim roamingConfig As System.Configuration.Configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.PerUserRoaming)
        'Debug.WriteLine(roamingConfig.FilePath)

    End Sub

    Public Sub SavePlayersData()
        My.Settings.PlayerId = Players.PlayerId
        My.Settings.PlayerData = Players.BuildSettings
    End Sub

    End Class

